package eu.ydp.mathplayer.editor.controller;

import gwt.g2d.client.graphics.Color;
import gwt.g2d.client.graphics.Surface;
import gwt.g2d.client.graphics.shapes.ShapeBuilder;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.FocusListenerAdapter;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.Widget;
import com.mathplayer.player.geom.Area;
import com.mathplayer.player.interaction.InteractionSocket;

public class InteractionManager implements InteractionSocket {

	private final int CURSOR_MARGIN = 2;
	
	private Area cursorPosition;
	private boolean focused = false;
	private boolean cursorVisible = false;

	private AbsolutePanel container;
	private AbsolutePanel canvasLayer;
	private AbsolutePanel cursorLayer;
	private FocusPanel focusLayer;
	private Surface cursorCanvas;
	
	private Timer timer;
	
	private ActionSocket actionSocket;
	
	@SuppressWarnings("deprecation")
	public InteractionManager(Panel owner, ActionSocket actionSocket){
		this.actionSocket = actionSocket;
		
		container = new AbsolutePanel();
		container.setStyleName("math-player-container");
		canvasLayer = new AbsolutePanel();
		canvasLayer.setStyleName("math-player-canvas");
		cursorLayer = new AbsolutePanel();
		cursorLayer.setStyleName("math-player-cursor");
		cursorLayer.setVisible(true);
		focusLayer = new FocusPanel();
		focusLayer.setStyleName("math-player-focus");
		
		container.add(canvasLayer, 0, 0);
		container.add(cursorLayer, 0, 0);
		container.add(focusLayer, 0, 0);
		
		owner.add(container);
		
		timer = new CursorTimer();
		timer.scheduleRepeating(500);
		
		focusLayer.addFocusHandler(new FocusHandler() {
			public void onFocus(FocusEvent event) {
				processFocus(true);
			}
		});
		focusLayer.addFocusListener(new FocusListenerAdapter() {
			public void onLostFocus(Widget sender) { 
				processFocus(false);
			}
		}); 
		final ActionSocket aSock = this.actionSocket;
		focusLayer.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				int x = event.getNativeEvent().getClientX() - focusLayer.getAbsoluteLeft() - CURSOR_MARGIN;
				if (x < 0)
					x = 0;
				else if (x > canvasLayer.getOffsetWidth() - CURSOR_MARGIN*2)
					x = canvasLayer.getOffsetWidth() - CURSOR_MARGIN*2;
				
				aSock.onClick(x, event.getNativeEvent().getClientY() - focusLayer.getAbsoluteTop());
			}
		});
	}
	
	@Override public void addGap(int x, int y) {	}
	@Override public int getTextBoxHeight() { return 0; }
	@Override public int getTextBoxWidth() { return 0; }

	@Override
	public void setCanvas(Widget canvas, int width, int height) {
		container.setSize(String.valueOf(width+CURSOR_MARGIN*2)+"px", String.valueOf(height)+"px");
		canvasLayer.clear();
		canvasLayer.setSize(String.valueOf(width+CURSOR_MARGIN*2)+"px", String.valueOf(height)+"px");
		canvasLayer.add(canvas, CURSOR_MARGIN, 0);

		cursorLayer.clear();
		cursorLayer.setSize(String.valueOf(width+CURSOR_MARGIN*2+"px"), String.valueOf(height)+"px");
		cursorCanvas = new Surface(width+CURSOR_MARGIN*2, height);
		cursorLayer.add(cursorCanvas, 0, 0);
		
		focusLayer.setSize(String.valueOf(width+CURSOR_MARGIN*2)+"px", String.valueOf(height)+"px");
		
	}

	@Override
	public void setCursorPosition(Area area) {
		cursorPosition = area;
		cursorPosition.x += CURSOR_MARGIN;
		drawCursor();
	}

	@Override
	public boolean isEditorMode() {
		return true;
	}

	public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
		return focusLayer.addKeyPressHandler(handler);
	}
	
	public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
		return focusLayer.addKeyDownHandler(handler);
	}

	
	public void drawCursor(){

		//cursorCanvas = new Surface(cursorLayer.getOffsetWidth(), cursorLayer.getOffsetHeight());
		//cursorLayer.clear();
		//cursorLayer.add(cursorCanvas, 0, 0);
		
		ShapeBuilder shapeBuilder = new ShapeBuilder();
		shapeBuilder.drawLineSegment(cursorPosition.x, cursorPosition.y, cursorPosition.x, cursorPosition.y+cursorPosition.height);
		cursorCanvas.clear();
		if (focused)
			cursorCanvas.setStrokeStyle(new Color(255, 0, 0));
		else
			cursorCanvas.setStrokeStyle(new Color(160, 160, 160));
		cursorCanvas.strokeShape(shapeBuilder.build());
	}
	
	
	public void processFocus(boolean focused){
		this.focused = focused;
		drawCursor();
		if (!focused)
			cursorLayer.setVisible(true);
		
	}
	
	public void setFocus(boolean focused){
		focusLayer.setFocus(focused);
	}
	
	protected class CursorTimer extends Timer{

		public void run() {
			if (focused){
				cursorVisible = !cursorVisible;
				cursorLayer.setVisible(cursorVisible);
			}
		}
	}

}
